昨天介紹 Service Workers 後我們知道它是 PWA 的要素之一,且也是讓 Web App 實現離線瀏覽的關鍵技術。今天我們將延伸昨天的知識,介紹 Application Shell Architecture
這個架構,並看看它能為網頁效能帶來什麼樣的優化。
Application Shell (App Shell
) 是建構 PWA 的要素之一,除了提升使用者體驗與載入速度外,也是實現離線瀏覽的一個關鍵。
不知道讀者有沒有在離線的時候分別點開 Web App 與 Native App 的經驗,通常 web 如果沒有特別做處理的話,一般會顯示 network error,使用者基本上什麼內容都看不到,且也沒辦法操作頁面。而 App 在這方面的行為就不太ㄧ樣了,雖然有些 App 仍然會限定一定要有網路才能操作,不過大部分的 App 應該都還是能正常開啟,即使很多操作都沒辦法在離線進行,至少使用者還是可以看到畫面或是看到之前的操作記錄,離線狀況的使用者體驗可以說是大勝 Web。
而 App Shell 就是讓 Web 也能達成這件事的技巧。
所謂 App Shell 指的是把 UI 上一些不常變動的部分 (例如 navbar, footer) 與需要動態抓取的部分(Dynamic Content)拆分開來,App Shell 在下載後可以存到 Service Workers 的快取裡,之後再次請求頁面時就可以迅速顯示快取的內容,並且在網路狀況不佳甚至離線時也可以從快取顯示 App Shell 的內容。
如果以 Native App 的角度來思考,App Shell 就很像在 Native App 中被開發並上架到 App Store 或是 Google Play 的核心程式碼,即使沒有網路,使用者仍然可以看見 App Shell 的建立出的骨幹畫面,剩下的內容都是透過網路請求動態去抓取。
總結一下,App Shell 應該要可以達到以下的功能與特性:
快速載入
將動態資料抽離
從快取中載入靜態資源
App Shell 的概念不難,但是在切分 App Shell 與 Dynamic Content 時要格外謹慎才能發揮最大的效益。
一般來說,設計 App Shell 時會考量到以下特點:
App Shell 越簡單越好
要包含足夠有意義的頁面內容
為了使用者體驗,可以包括一些 placeholder 之類的元件
就以 Google 推薦的離線版維基百科為例為例,我使用 DevTool 模擬了一下 offline 時網站的顯示狀況
可以推測出 App Shell 的內容應該包括上方的搜尋欄位與下方灰色的 body。
至於 Dynamic Content 也是可以放到快取中以便 offline 時使用者可以繼續瀏覽已經載入過的內容以提升使用者體驗,不過這麼做的話就要注意資料新鮮度的問題,要盡量做到網路連線恢復時能讓使用者看到最新版的資料。
以這個離線版本的維基百科來說,它會把之前動態載入的 JSON 檔案也放到 Service Workers 快取中,以便離線時也能夠瀏覽。
採用 App Shell 架構在第一次渲染時會需要比較久的時間,因為需要在瀏覽器註冊 Service Workers 並且將屬於 Shell 的靜態資源放到 Services Workers 的 Cache 裡,不過之後的請求因為可以從 Cache 立即顯示 Shell 的元件,所以會有較快的 First Meaningful Paint (FMP),之後再靠 Ajax 的方式抓取動態的資料並渲染到畫面上。
這個方式也讓使用者的「感知效能」提升,雖然使用者還是必須等待動態資料回傳後才能操作網頁,但我們卻可以利用一些小技巧讓使用者可以先看到部分畫面,降低等待頁面的痛苦。
關於 App Shell 對於載入時間的影響可以參考 Google 在 3G 網路環境下做的實驗。
當頁面有許多動態內容時採用 App Shell 架構去拆分出靜態 Shell 與動態內容會比較有意義,如果網站規模很小或是內容基本上都是靜態的話,採用 App Shell 會有點失去意義,畢竟如果都是靜態內容,整個網站 build 完後都可以放到快取中。
在一些比較舊瀏覽器或是比較輕量級的瀏覽器例如在東南亞十分流行的 KaiOS 就還沒有支援 Service Workers,那這時候該怎麼辦呢?
還記得在昨天 Day18 的內容有提到 Service Workers 的 Cacahe 應該要跟 HTTP Cache 彼此搭配嗎?透過設置 HTTP Cache Control 的 header,就可以讓沒有支援 Service Workers 的瀏覽器仍然能透過 Browser Caching 保障一定的效能體驗。
今天的內容雖然跟其他篇相比稍嫌簡短(明天又會恢復長篇大論來折磨讀者了XDD),但我認為還蠻受用的。雖然 PWA 可能不像一開始推出時所說的可以取代 Native App (至少在 iOS 那麼多功能不支援的狀況下是不太可能的),但其實 PWA 本身就不是一個明確的技術,而是一個漸進式的概念,許多支援相對完整的功能是值得學習與套用在的專案上的,離線瀏覽就是其中一個非常重要的功能。
透過 App Shell 架構,讓使用者有機會在沒有網路連線時也能夠保有最低限度的使用者體驗,並且也透過快取加快了頁面的載入速度。如果網站的內容可以明確分為動態的內容與靜態的「殼」,就十分推薦可以試試看採用 App Shell 架構喔!
至於如何實作 App Shell 架構,其實結合昨天與今天兩篇文章讀者應該就能自行推敲出作法,如果想要更完整的教學,可以參考 Google 關於 Offline Web App 的 Lab。
到目前為止介紹了 Browser Cache 與 Service Workers Cache 兩種快取,但你以為兩層防護就是極限了嗎?還有!明天將介紹 Web 開發者不可以不知道的技術 - CDN,我們明天見。
https://developers.google.com/web/fundamentals/architecture/app-shell?hl=zh_tw
https://developers.google.com/web/showcase/2016/iowa2016?hl=zh_tw
https://developers.google.com/web/updates/2015/11/app-shell